//
// Created by cyber on 2021/8/20.
//
#include <iostream>
#include <set>
using namespace std;
class Folder;
class Message
{
    friend class Folder;

public:
    friend void swap(Message&,Message&);
    //folders被隐式初始化为空集合
    explicit Message(const std::string & str = "")
        : contents(str)
    {}
    //拷贝控制成员，用来管理指向本Message的指针
    Message(const Message &);            //拷贝构造函数
    Message & operator=(const Message &);//拷贝赋值运算符
    ~Message();                          //析构函数

    Message(Message && m);
    Message & operator=(Message && rhs);
    //从给定Folder集合中添加/删除本Message
    void save(Folder &);
    void remove(Folder &);

private:
    std::string        contents;//实际消息文本
    std::set<Folder *> folders; //包含本Message的 Folder//拷贝构造函数、拷贝赋值运算符和析构函数所使用的工具函数

private:
    //将本Message添加到指向参数的Folder中
    void add_to_Folders(const Message &);

    //从folders中的每个Folder中删除本Message
    void remove_from_Folders();

    //从本 Message移动Folder指针
    void move_Folders(Message * m);
};
class Folder;
Message::Message(const Message & m)
    : contents(m.contents)
    , folders(m.folders)
{
    add_to_Folders(m);  //将本消息添加到指向m的 Folder中
}

Message::~Message()
{
    remove_from_Folders();
}
void Message::save(Folder &f)
{
    folders.insert (&f);//将给定Folder添加到我们的Folder列表中
    f.addMsg(this);     //将本Message添加到f的 Message集合中
}
void Message::remove(Folder &f)
{
    folders.erase(&f);  //将给定Folder从我们的 Folder列表中删除
    f.remMsg(this);     //将本 Message从f的Message集合中删除
}
void Message::add_to_Folders(const Message &m)
{
    for (auto f : m.folders)    //对每个包含m的Folder
        f->addMsg(this);        //向该Folder添加一个指向本Message 的指针

}
void Message::remove_from_Folders()
{
    for(auto f : folders)//对folders中每个指针
        f->remMsg(this); //从该Folder 中删除本 Message
}
Message & Message::operator=(const Message & rhs)
{
    //通过先删除指针再插入它们来处理自赋值情况
    remove_from_Folders();  //更新已有Folder
    contents = rhs.contents;//从rhs拷贝消息内容
    folders  = rhs.folders; //从 rhs拷贝Folder指针
    add_to_Folders(rhs);    //将本 Message 添加到那些Folder中
    return *this;
}
void swap(Message & lhs, Message & rhs)
{
    using std::swap;//在本例中严格来说并不需要，但这是一个好习惯
    // 将每个消息的指针从它（原来）所在Folder中删除
    for(auto f : lhs.folders)
        f->remMsg(&lhs);
    for(auto f : rhs.folders)
        f->remMsg(&rhs);

    //交换contents和Folder指针set
    swap(lhs.folders, rhs.folders); //使用swap(set&, set&)
    swap(lhs.contents, rhs.contents);// swap(string&,string&)

    // 将每个 Message的指针添加到它的（新)Folder中
    for(auto f : lhs.folders)
        f->addMsg(&lhs);
    for(auto f : rhs.folders)
        f->addMsg(&rhs);
}

//从本 Message移动Folder指针
void Message ::move_Folders(Message * m)
{
    folders = std::move(m->folders);//使用set的移动赋值运
    //对每个Folder
    for(auto f : folders) {
        f->remMsg(m);       //从Folder中删除旧Message
        f->addMsg(this);    //将本Message添加到Folder中
    }
    m->folders.clear();//确保销毁m是无害的
}

class Folder{
    friend class Message;
public:
    Folder();
    ~Folder();
    Folder(const Folder &);
    Folder & operator=(const Folder &);
    void     addMsg(Message * m) { msgs.insert(m); }
    void     remMsg(Message * m) { msgs.erase(m); }
    void     addFldr(Folder * f) { folders.insert(f); }//添加给定Folder
    void     remFldr(Folder * f) { folders.erase(f); }

private:
    set<Message *> msgs;
    set<Folder *>   folders;
    void           add_to_Messages(const Folder & f);
    void           remove_from_Msgs();

};
Message::Message(Message && m)
{
    move_Folders(&m);
}
Message & Message::operator=(Message && rhs)
{
    //直接检查自赋值情况
    if(&rhs != this) {
        remove_from_Folders();
        contents = std::move(rhs.contents);//移动赋值运算符
        move_Folders(&rhs);                //重置Folders指向本Message
    }
    return *this;
}

void Folder::add_to_Messages (const Folder &f)
{
    for(auto msg : f.msgs)
        msg->addFldr(this);//将这个Folder添加到所有Message 中
}

void Folder::remove_from_Msgs()
{
    while(!msgs.empty())            //将这个Folder从它所有Message 中删除
        (*msgs.begin())->remove(*this);
}

//删除给定Folder
void Message::remove(Folder & f)
{
    folders.erase(&f);//将Folder从此 Message中删除
    f.remMsg(this);   //反向:将Message 也从 Folder 中删除
}

Folder::Folder(const Folder & f)
    : msgs(f.msgs)
{
    add_to_Messages(f);//将Folder添加到它所有Message 的folders中
}
Folder::Folder()
{
}
Folder::~Folder()
{
    remove_from_Msgs();
}
Folder & Folder::operator=(const Folder &f)
{
    remove_from_Msgs();//从每个Message中删除此Folder
    msgs = f.msgs;     //从右侧运算对象拷贝 Message集合

    add_to_Messages(f);//将此Folder添加到每个新Message中
    return *this;
}
